Skip to content

Refactor: replaced mannual calculation to library** =@use-gesture/react library#43

Closed
aniket866 wants to merge 5 commits intoAOSSIE-Org:mainfrom
aniket866:added-more-guestures
Closed

Refactor: replaced mannual calculation to library** =@use-gesture/react library#43
aniket866 wants to merge 5 commits intoAOSSIE-Org:mainfrom
aniket866:added-more-guestures

Conversation

@aniket866
Copy link
Contributor

@aniket866 aniket866 commented Feb 9, 2026

First of all replaced mannual calculation to library =@use-gesture/react library
reason: faster** processing ,less prone to errors by mannual calculations

Deleted Manual Math Logic (The biggest chunk)

  • Removed: src/utils/math.ts

  • Reason: Previously, the app had to manually calculate distances, angles, and velocities between touch points to detect pinches and zooms. This required a lot of raw math code.

  • Replacement: The new @use-gesture/react library handles all this math internally. We no longer need to maintain complex vector geometry functions.

  1. Simplified Gesture Hook
    File: src/hooks/useTrackpadGesture.ts

Change: We deleted the large blocks of code that manually listened to onTouchStart, onTouchMove, and onTouchEnd and tried to figure out "is this a scroll or a drag?".

Summary of Updates: updated versions of:

  • package.json (Added dependency)

  • src/utils/math.ts (Cleaned up)

  • src/hooks/useTrackpadGesture.ts (Rewritten with library)

  • src/components/Trackpad/TouchArea.tsx (Updated props)

  • src/routes/trackpad.tsx (Updated hook usage)

  • src/server/InputHandler.ts (Verified)

Closes #41

Thankyou

Summary by CodeRabbit

  • New Features

    • Directional swipe gestures (up/down/left/right) added for quick actions.
  • Improvements

    • Smoother, more reliable multi-touch gesture tracking and unified touch behavior.
    • Simplified trackpad interactions and immediate text input handling.
  • Bug Fixes

    • More robust input processing with centralized error handling.
  • Chores

    • Added a gesture library dependency to support the new gesture system.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds @use-gesture/react; replaces bespoke touch handling with a gesture-driven hook returning spreadable handlers; updates TouchArea to accept generic handlers and remove its tracking indicator; InputHandler replaces zoom with swipe, adds direction, centralizes error handling; removes some touch/time constants from math utils.

Changes

Cohort / File(s) Summary
Dependency Addition
package.json
Added dependency @use-gesture/react (^10.3.1).
Trackpad UI
src/components/Trackpad/TouchArea.tsx
Replaced explicit touch props with a permissive handlers: any and spread ...handlers onto the root element; removed internal touch helpers and the visual tracking/loading indicator; added onContextMenu preventDefault and streamlined focus/interaction wiring.
Gesture Hook
src/hooks/useTrackpadGesture.ts
Rewrote to use @use-gesture/react (gesture binder). Removed manual per-touch state and the optional sensitivity parameter — new signature is useTrackpadGesture(send, scrollMode); returns { isTracking, handlers } where handlers is the binder output.
Server Input Handling
src/server/InputHandler.ts
Replaced zoom message with swipe + direction; increased mouse speed constant; wrapped message processing in try/catch with centralized error logging; refactored move/click/scroll/key/text handling and normalized inputs.
Math Utilities
src/utils/math.ts
Removed exported constants TOUCH_MOVE_THRESHOLD, TOUCH_TIMEOUT, and PINCH_THRESHOLD; left acceleration logic intact.
Route Input Flow
src/routes/trackpad.tsx
Simplified hidden-input and keyboard/text handling: removed composition batching and delayed click simulation; sends text immediately on input change and simplifies left/right click flows and focus-on-container behavior.

Sequence Diagram(s)

sequenceDiagram
    participant User as User (Trackpad)
    participant TouchArea as TouchArea
    participant GestureLib as "@use-gesture/react"
    participant Hook as useTrackpadGesture
    participant Server as InputHandler

    User->>TouchArea: perform gesture (touch/pointer)
    TouchArea->>Hook: spread handlers (DOM events)
    Hook->>GestureLib: gesture binder receives events
    GestureLib->>Hook: emits drag/pinch/tap etc.
    Hook->>Server: send({ type: 'move'|'scroll'|'swipe'|'click'|'text', ... })
    Server->>Server: handleMessage() wrapped in try/catch -> execute mapped input actions
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped on code with eager paws,

I swapped raw touches for gesture laws,
Swipes and drags now travel light,
Events bound neat and routed right,
A little hop for input's cause!

🚥 Pre-merge checks | ✅ 2 | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Changes to InputHandler.ts (replacing 'zoom' with 'swipe', adjusting mouse speed, refactoring event handling) extend beyond the @use-gesture/react integration and appear to be related improvements rather than core migration requirements. Clarify whether InputHandler.ts changes (zoom→swipe type change, mouse speed adjustment) are required for the gesture library migration or if they should be separate. Justify architectural decisions.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title refers to replacing manual calculations with @use-gesture/react, which is a real aspect of the change, but it has spelling errors ('mannual' instead of 'manual') and awkward phrasing ('to library** =@use-gesture/react library'). It is partially related to the main change but lacks clarity and professionalism. Revise the title to correct spelling errors and improve clarity. Suggested: 'Refactor: Replace manual gesture calculations with @use-gesture/react library.'
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully implements the core objective from issue #41 by migrating gesture handling to @use-gesture/react, removing manual math, and improving gesture handling reliability across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In `@src/components/Trackpad/TouchArea.tsx`:
- Around line 3-8: TouchAreaProps declares isTracking but the TouchArea
component never consumes it; remove the unused required prop or make it optional
to avoid forcing callers to pass a noop value. Update the TouchAreaProps
interface by deleting the isTracking: boolean entry (or change it to
isTracking?: boolean) and then run a quick search for TouchAreaProps/type usages
to adjust any call sites or tests that currently supply isTracking so they no
longer must provide it; ensure handlers and status remain unchanged.

In `@src/hooks/useTrackpadGesture.ts`:
- Around line 52-61: The setTimeout in onDragEnd can call send after unmount;
fix by tracking the timeout ID in the useTrackpadGesture hook (e.g., a timeoutId
ref) and either clearTimeout(timeoutId.current) before scheduling and on the
hook cleanup, or add a mounted ref check that prevents calling send if
unmounted. Update onDragEnd to store the returned timer id when scheduling the
second click, clear any prior timer before creating a new one, and add a cleanup
effect that clears timeoutId.current (or flips mounted to false) so send is
never invoked after unmount.
- Around line 36-50: In the touches === 3 branch the code zeroes both axes when
one threshold is hit, so a diagonal swipe drops the second direction; update the
logic in the swipe handling inside the touches === 3 block (where
swipeAccumulator.current, SWIPE_THRESHOLD and send are used) to only reset the
axis that triggered the send (i.e., set swipeAccumulator.current.x = 0 when
sending an x swipe and swipeAccumulator.current.y = 0 when sending a y swipe) so
the other axis value is preserved and can still trigger its own send.

In `@src/server/InputHandler.ts`:
- Around line 47-62: Wrap each switch case body in InputHandler.ts inside its
own block to prevent scope leakage for block-scoped declarations: for the
'scroll' case (where const invert is declared) and the 'zoom' case (and any
other cases declaring const/let), surround the case's statements with { ... } so
that const invert and other variables are block-scoped to their case; update the
case labels for 'scroll' and the 'zoom' handling in the switch inside the
InputHandler class (or function) accordingly, ensuring no identifiers like
invert are declared twice across sibling cases.
- Around line 81-109: The 'swipe' case in InputHandler.ts risks leaving
modifiers pressed if keyboard.type() throws; wrap each modifier sequence in a
try/finally so that any pressed keys are always released — for example, after
calling keyboard.pressKey(Key.LeftSuper) and keyboard.pressKey(Key.LeftControl)
ensure a finally block calls keyboard.releaseKey(Key.LeftControl) and
keyboard.releaseKey(Key.LeftSuper); do the same for the other branches that
press LeftSuper (up/down/right) so every pressKey has a matching releaseKey in a
finally block around keyboard.type() calls.
🧹 Nitpick comments (2)
src/server/InputHandler.ts (1)

83-83: Remove debug console.log or downgrade to a debug-level log.

This will fire on every 3-finger swipe in production. If a structured logger is available, use it at debug level; otherwise, remove the line.

src/hooks/useTrackpadGesture.ts (1)

4-5: send parameter typed as any — loses type safety with InputMessage.

Since InputMessage is already defined in src/server/InputHandler.ts, importing and using it here would catch malformed messages at compile time (e.g., a missing direction on swipe, or a typo in the type field).

♻️ Suggested change
+import type { InputMessage } from '../server/InputHandler';
+
 export const useTrackpadGesture = (
-    send: (msg: any) => void,
+    send: (msg: InputMessage) => void,
     scrollMode: boolean,
     sensitivity: number = 1.5
 ) => {

@aniket866 aniket866 force-pushed the added-more-guestures branch from 3321e6f to eca54c5 Compare February 9, 2026 18:32
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/hooks/useTrackpadGesture.ts`:
- Around line 21-47: onDrag currently ignores drags when maxFingers.current >= 3
so three-finger swipe gestures are dropped; implement a branch in the onDrag
handler that detects three-finger gestures by accumulating scaledDx/scaledDy
into a three-finger gesture accumulator (e.g., threeFingerDelta or similar
state), apply a configurable threshold to determine direction
(left/right/up/down) and then call send(...) with the appropriate gesture event
(e.g., 'switch-desktop' / 'task-view' / 'show-desktop' or a single
'three_finger_swipe' with direction payload), and ensure the accumulator is
reset on drag end (onDrag end handler) and that sensitivity, maxFingers.current,
and scrollMode logic remain unchanged; if three-finger behavior was
intentionally omitted, update the PR description instead.
🧹 Nitpick comments (2)
src/hooks/useTrackpadGesture.ts (1)

50-61: onPinchStart sets tracking but doesn't coordinate with onDragStart/onDragEnd for maxFingers.

onPinchStart sets isTracking = true but never touches maxFingers. If a pinch fires without a drag (or after drag ended and reset maxFingers to 0), a subsequent onDragEnd tap check would see maxFingers === 0 and skip the click — which is probably fine. But if onPinchEnd fires before onDragEnd, isTracking is set to false while the drag may still be active. Consider whether the two tracking states should be independent.

src/components/Trackpad/TouchArea.tsx (1)

6-6: handlers: any defeats type safety.

Consider using a more specific type. use-gesture's bind() returns React.DOMAttributes<HTMLDivElement> (or similar). At minimum, React.HTMLAttributes<HTMLDivElement> would catch typos and invalid handler props at compile time.

-    handlers: any; // Accepts the spreadable event handlers from `@use-gesture/react`
+    handlers: React.DOMAttributes<HTMLDivElement>;

@aniket866
Copy link
Contributor Author

hi @imxade I have completed the the migration from mannual math calculation to @use-gesture/react library
Please checkout whenever you get your free time

Thankyou so much

Copy link

@anchalkapoor424 anchalkapoor424 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reviewed and almost everything is good to go on.
nice idea by maintainer to replace manual calculation to library based approach,

@imxade
Copy link
Contributor

imxade commented Feb 10, 2026

@aniket866 it's not behaving properly in my case (NixOS, Wayland)

two finger scrolling zooms

tapping doesn't register a click

@aniket866
Copy link
Contributor Author

@aniket866 it's not behaving properly in my case (NixOS, Wayland)

two finger scrolling zooms

tapping doesn't register a click

hi @imxade , thankyou for review my PR
i have checked once again, in my case tapping is working ,
but you are right two finger scrolling zooms if not done perfectly ,because it can't able to distinguish b/w scroll and zoom done by 2 fingers, so I am working on that part , to fix this issue of 2 finger
, updating you soon,

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/hooks/useTrackpadGesture.ts`:
- Around line 28-52: The onDrag handler in useTrackpadGesture is using the
per-frame delta value to detect if movement exceeds TAP_MOVE_THRESHOLD, which
causes slow drags with small frame-by-frame movements to be incorrectly
identified as taps. Replace the threshold check that uses delta (obtained from
destructuring the delta property) with a check using the cumulative movement
value instead. Extract movement from the gesture event parameter and use
Math.abs(movement[0]) and Math.abs(movement[1]) in the comparison against
TAP_MOVE_THRESHOLD, while continuing to use delta for the scroll and move event
payloads.
- Around line 54-72: The bug is that touchCountRef is only updated in onDrag so
zero-movement taps read a stale value; update touchCountRef when pointers start
by capturing the current pointer/finger count in onPointerDown (or onTouchStart)
so onPointerUp uses the correct value; locate touchCountRef, onPointerUp and
onDrag in useTrackpadGesture.ts and add logic in onPointerDown (or the gesture
library's touch-start handler) to set touchCountRef.current to the active
pointer count before computing button and calling send({type: 'click', ...})
using TAP_TIME for tap detection.

In `@src/routes/trackpad.tsx`:
- Around line 50-55: onLeftClick and onRightClick currently call send(...) with
press: true and never send a release, leaving buttons held on the server; update
those callbacks to mirror the tap handler pattern in useTrackpadGesture.ts by
sending the press=true event immediately via send({ type: 'click', button:
'left'|'right', press: true }) and then scheduling a release with a short
setTimeout that calls send({ type: 'click', button: 'left'|'right', press: false
}); ensure you reference the existing send function and the same delay
value/pattern used by the tap handler to keep behavior consistent.
🧹 Nitpick comments (4)
src/server/InputHandler.ts (2)

50-55: Scroll threshold removed — small noisy deltas will now fire scroll calls.

The previous implementation had a Math.abs(amount) >= 0.1 guard. The new code fires mouse.scrollDown / mouse.scrollRight for any truthy msg.dy / msg.dx, including very small fractional values that @use-gesture/react may emit on every frame. This could cause jittery scrolling or unnecessary IPC overhead.

Consider re-adding a minimum threshold:

Proposed fix
 case 'scroll': {
     const invert = CONFIG.MOUSE_INVERT ? -1 : 1;
-    if (msg.dy) await mouse.scrollDown(msg.dy * invert);
-    if (msg.dx) await mouse.scrollRight(msg.dx * invert);
+    const dy = msg.dy ? msg.dy * invert : 0;
+    const dx = msg.dx ? msg.dx * invert : 0;
+    if (Math.abs(dy) >= 0.5) await mouse.scrollDown(dy);
+    if (Math.abs(dx) >= 0.5) await mouse.scrollRight(dx);
     break;
 }

50-55: await mouse.getPosition() on every move event adds latency on the hot path.

Every single pointer-move event round-trips through mouse.getPosition() (Line 26) before setting the new position. For a high-frequency drag stream this can introduce noticeable cursor lag, especially on systems where nut-js queries the OS synchronously under the hood. If @nut-tree-fork/nut-js exposes a relative-move API (e.g., mouse.move(...) with a direction/offset), that would avoid the read entirely.

Also applies to: 24-33

src/components/Trackpad/TouchArea.tsx (2)

6-6: handlers: any discards type safety.

The gesture binder from @use-gesture/react returns a well-typed object. Typing this as any silently swallows mismatches. A more precise type preserves safety without coupling to internal library types:

Proposed fix
 interface TouchAreaProps {
     scrollMode: boolean;
     isTracking: boolean;
-    handlers: any;
+    handlers: React.DOMAttributes<HTMLDivElement>;
     status: 'connecting' | 'connected' | 'disconnected';
 }

17-21: Consider adding role="application" for the interactive touch surface.

Biome flags this <div> for noStaticElementInteractions since it receives pointer/touch handlers but has no ARIA role. For a virtual trackpad surface, role="application" is the most semantically appropriate choice, signaling that the region has custom interaction semantics.

Proposed fix
         <div
             className="flex-1 bg-neutral-800 relative touch-none select-none flex items-center justify-center p-4"
+            role="application"
             {...handlers}
             onContextMenu={(e) => e.preventDefault()}
         >

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@aniket866
Copy link
Contributor Author

hi @imxade
I have applied the fix you suggested,

now this PR involves

  1. migrate from manual math calculation to react library
  2. single tap->left click
  3. double finger tap= right click
  4. 2 finger drag->scroll -->>> test it scroll up down may be in your device scroll is inverted so you can check both way up and down
  5. currently zoom is not implemented in this PR , because of logic conflict b/w double finger scroll and zoom , so I will cover that feature in separatly to keep this PR clean ,

I tried to implement zoom but sensitivity is too high causing accidental zoom-in and zoom-out, so I think we need to work on zoom separately for adding smooth zoom with showing zoom percentage , that will be totally different task so I will fix that soon in another PR.

I have made this PR ready to be merged removing all merge conflicts , so can be merged , let me know if any issue

  • you can test locally all features are working

thankyou , @imxade

@imxade imxade closed this Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Better way to implement trackpad behavior

3 participants